import { Client, ClientConfig, ClientEvent } from 'amesu';
import { BOT_EventType, BOT_MSGID_MAP, BOT_MSG_AT, BOT_OnData, BOT_READY } from './botType';
import { error, info, log } from 'console';
import { sendImage } from './sendLocaImage';
import { Emitter_bot } from '../msgHandle/packge';
import { Bot_msg } from './bot_msg';
import func from '../func';
import browser, { tempDir } from '../browser/browser';
let msgSeq = {}

const EventEmitter = require('events');
class bot extends EventEmitter {
  private user: any;
  private config?: ClientConfig;
  private client: Client;
  private api: Client['api'];
  private msgIdMap: Map<string, Map<string, BOT_MSGID_MAP>>; //消息id哈希表，子频道ID，消息ID
  /**
   * 消息ID
   * 触发指令
   */
  private machMap: Map<string, string>;

  public guildMap: unknown;
  public userActiveChannelMap: unknown;
  public channelMap: unknown;
  private is_online: boolean;

  constructor() {
    super();

    this.machMap = new Map();
    this.msgIdMap = new Map();
    this.guildMap = new Map();
    this.userActiveChannelMap = new Map();
    this.channelMap = new Map();
    this.is_online = false;
  }

  getBotConfig(): ClientConfig {
    return (
      this.config || {
        appid: '666',
        token: '666',
        secret: '',
        events: [],
        sandbox: true,
      }
    );
  }

  //   at(id: string) {
  //     return `<@!${id}>`;
  //   }

  /**
   * 设置机器人配置
   * @param config
   */
  setBotConfig(config: ClientConfig) {
    info('BOT初始化开始');

    switch (true) {
      case !config:
        return error('没有机器人配置');
      case !config.events.length:
        return error('BOT配置项:events错误');
    }
    this.config = config;
    this.client = new Client(this.config);
    this.client.on('session.ready', data => {
      this.user = data.user;

      if (this.is_online) {
        console.info('重复READY');
        return;
      } else {
        this.is_online = true;
        this.api = this.client.api;
      }
      this.emit(Emitter_bot.login_succress, data);

      const events: (keyof ClientEvent)[] = [
        // DIRECT_MESSAGE
        'direct.message.create',
        'direct.message.delete',
        // GUILD_MESSAGES
        'message.create',
        'message.delete',
        // PUBLIC_GUILD_MESSAGES
        'at.message.create',
        'public.message.delete',
        // GROUP_MESSAGES
        'group.at.message.create',
      ];

      for (let index = 0; index < events.length; index++) {
        const event = events[index];

        this.client.on(event, async (data: any) => {
          this.on_event(event, data);
        });
      }
    });
    this.client.online();
  }

  getBotInfo() {
    return this.user;
  }

  private async on_event(event: keyof ClientEvent, data: any) {
    if (data.t == 'AT_MESSAGE_CREATE' || data.t == 'GROUP_AT_MESSAGE_CREATE') {
      let _msg = new Bot_msg(data);
      this.emit(Emitter_bot.user_input, _msg);
    }
  }

  /**
   * 发送消息 API
   *
   * @param id 群 or 频道 id
   * @param message 消息体
   */
  private async postMessage(id: string, message: any) {
    if (message.image && message.image.includes('127.0.0.1')) {
      return;
    }
    const is_group = id.length === 32;
    if (is_group && message.content) {
      message.content = `\n${message.content}`
    }
    return is_group
      ? this.api.sendGroupMessage(id, message)
      : this.api.sendChannelMessage(id, message);
  }

  private getMsgId(id: string): string | undefined {
    let nowTime = Date.now();
    let timeOut = 5 * 60 * 950;
    let msg_id;
    // 在哈希表中查找适合的消息id
    this.msgIdMap.forEach((itemMap, channel) => {
      if (id == channel) {
        itemMap.forEach((item, msgId) => {
          if (nowTime - item.creatorTime > timeOut) {
            // 已过期
            itemMap.delete(msgId);
            msg_id = 0;
            return 0;
          }
          if (item.surplusCont <= 0) {
            // 已使用完可用次数
            item.surplusCont = 5;
            msg_id = 1;
            return 1;
          }
          item.surplusCont -= 1;
          msg_id = msgId;
        });
      }
    });
    return msg_id;
  }

  /**
   * 发送文字内容
   *
   * @param id 群 or 频道 id
   * @param content 文字内容
   * @param triggerKey 表情指令
   */
  async sendText(id: string, content: string, tryCont: number = 0) {
    let msg_id;

    console.info('【发送消息】', content);
    msg_id = this.getMsgId(id);
    if (msg_id == 1) {
      await new Promise(rs => {
        setTimeout(rs, 500);
      });
      msg_id = this.getMsgId(id);
    }
    // 单频道1秒内只能发送5条消息
    // TODO：后期考虑利用每天主动消息
    if (!msg_id) {
      log('sendText:没有找到可用消息ID');
      return;
    }
    if (typeof (msgSeq[msg_id]) == 'undefined') {
      msgSeq[msg_id] = 1;
    } else {
      msgSeq[msg_id] += 1;
    }
    await this.postMessage(id, {
      content: content,
      msg_id: msg_id,
      msg_seq: msgSeq[msg_id]
    })
      .catch((err) => {
        // if (tryCont < 1) {
        //   tryCont += 1;
        //   setTimeout(() => {
        //     this.sendText(id, `⚠️原消息发送失败,正在重试第${tryCont}次（1次后开始尝试图片发送)`, tryCont)
        //   }, 100)
        //   setTimeout(() => {
        //     this.sendText(id, content, tryCont)
        //   }, 300);
        // } else if (tryCont == 1) {
        // let list = content.split('\n');
        // console.error(list)
        // browser.render(tempDir.通用文字, {
        //   list: list
        // }).then((png) => {
        //   this.sendLocaImage(id, png);
        // });
        // // }
        // // 判定是否是艾特全体没有权限导致
        // if (content.includes('@everyone')) {
        //   log('没有艾特全体权限,尝试普通消息发送');
        //   this.sendText(id, content.replace('@everyone', ''));
        // } else {
        //   error('消息发送错误', msg_id, content);
        // }
      })
      .then(res => {
        // if (triggerKey) {
        //   if (res && res.data && res.data.id) {
        //     this.machMap.set(res.data.id, triggerKey);
        //   }
        // }
      });
  }

  async sendLocaImage(id: string, pathStr: string) {
    let msg_id;
    if (!id || id.length <= 0) {
      return;
    }
    msg_id = this.getMsgId(id);
    if (msg_id == 1) {
      await new Promise(rs => {
        setTimeout(rs, 500);
      });
      msg_id = this.getMsgId(id);
    }
    // 单频道1秒内只能发送5条消息

    // TODO：后期考虑利用每天主动消息
    if (!msg_id) {
      error('sendLocaImage:没有找到可用消息ID');
      return;
    }
    if (func.pngDir == '127.0.0.1') {
      await sendImage(msg_id, id, pathStr);
      return
    }
    this.sendImage(id, pathStr)
  }

  /**
   * 发送群图片（仅支持线上 URL）
   *
   * @param id - 群 id
   * @param msg_id - 消息 id
   * @param url - 图片 URL
   */
  async sendGroupMessage(id: string, msg_id: string, url: string): Promise<void> {
    if (url.includes('127.0.0.1')) {
      return;
    }
    const result: any = await this.api.sendGroupFile(id, {
      file_type: 1,
      srv_send_msg: false,
      url,
    });
    await this.api.sendGroupMessage(id, {
      msg_id,
      msg_type: 7,
      content: '',
      media: {
        file_info: result.data.file_info,
      },
    });
  }

  parseImageUrl(url: string): string {
    if (func.pngDir == '127.0.0.1') {
      return url
    } else {
      return `https://${func.pngDir}/${url.replace(/^\.\/html\/public\//, '')}`;
    }
  }

  /**
   * 发送图片内容
   *
   * @param id 群 or 频道 id
   * @param url 图片 URL
   */
  async sendImage(id: string, url: string): Promise<void> {
    let msg_id;


    msg_id = this.getMsgId(id);
    if (msg_id == 1) {
      await new Promise(rs => {
        setTimeout(rs, 500);
      });
      msg_id = this.getMsgId(id);
    }
    // 单频道1秒内只能发送5条消息


    // TODO：后期考虑利用每天主动消息
    if (!msg_id) {
      log('sendImage:没有找到可用消息ID');
      return;
    }
    const is_group = id.length === 32;
    const image = this.parseImageUrl(url);

    log(`sendImage:${image}`);
    try {
      is_group
        ? await this.sendGroupMessage(id, msg_id, image)
        : await this.postMessage(id, { msg_id, image });
    } catch (error) {
      error('图片消息发送错误');
    }
  }

  addMsgId(data: Bot_msg) {
    // 将消息存入哈希表内
    let itemMap;
    const msgData = {
      lastSendTime: Date.now(),
      surplusCont: 5,
      creatorTime: Date.now(),
    };
    if (this.msgIdMap.has(data.getFormId())) {
      itemMap = this.msgIdMap.get(data.getFormId());
    } else {
      itemMap = new Map();
      this.msgIdMap.set(data.getFormId(), itemMap);
    }
    itemMap.set(data.getMsgid(), msgData);
  }
}
export default new bot();
